// Copyright 2009 Jan Hosang <jan.hosang@gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package recipes

import (
    "fmt"
    "strings"
    "container/list"
    "os"
    
    "gb/invocation"
    "gb/tools"
)

type Dependency struct {
    sources *list.List
    label string
    output, deps []string
    cmds *list.List
}

func (d *Dependency) Label() string          { return d.label }
func (d *Dependency) Output() []string       { return d.output }
func (d *Dependency) Dependencies() []string { return d.deps }
func (d *Dependency) String() string         { return "" }

var dependencyLabels = map[string] bool {
    "Depends": true,
    "SubDir": true,
    "Shell": true,
}
func isDependency(label string) bool {
    _, ok := dependencyLabels[label]
    return ok
}

func newDependency(targets, sources, invocations *list.List) *Dependency {
    deps := list.New()
    cmds := list.New()
    for invEl := range invocations.Iter() {
        inv := invEl.(*invocation.Invocation)
        switch(inv.Label) {
            case "Depends":
                for src := range inv.Sources.Iter() {
                    deps.PushBack(src)
                }
            case "SubDir":
                panic("unimplemented")
            case "Shell":
                cmds.PushBack((interface{})(inv.Sources))
            default:
                fmt.Printf("Warning: Don't know how to behave on `%v'. Ignored.\n", inv)
        }
    }
    
    dep := new(Dependency)
    dep.sources = sources
    dep.output = tools.ListToStrSlice(targets)
    dep.label = strings.Join(dep.output, ":")
    dep.deps = tools.ListToStrSlice(deps)
    dep.cmds = cmds
    return dep
}

func (d *Dependency) ModTime() (modTime int64) {
    modTime = 0
    for source := range d.sources.Iter() {
        tModTime, _ := getModTime(source.(string))
        modTime = max(modTime, tModTime)
    }
    return
}

func getModTime(filename string) (int64, os.Error) {
    dir, err := os.Stat(filename)
    if err != nil {
        return 0, err
    }
    return dir.Mtime_ns, nil
}

func max(a, b int64) int64 {
    if a < b {
        return b
    }
    return a
}
